/**
 * @brief 循环存储框架
 * 
 */

/************************************
	flash循环存储框架
	* 使用者配置 flash存储起始地址，存储区大小 需要预留保存参数的空间
	* 在 DeviceParamsTypeDef 中定义 实际存储参数的类型（外部引入）
	* 添加flash驱动函数。
	
	note:
		H5芯片 flash写一次写入16给字节，所以要求 存储单元的大小为16字节的倍数。
		H5芯片 flash擦写需要关闭ICACHE.
	用法：
		初始化调用：FlashStorage_Init
		创建 DeviceParamsTypeDef临时变量，使用 FlashStorage_ReadLatestParams 读取最新配置参数
		创建 DeviceParamsTypeDef临时变量，将需要保存的数据填入，调用FlashStorage_WriteParams保存。
		
		
*************************************/

#ifndef FLASH_CYCLE_STORAGE_H
#define FLASH_CYCLE_STORAGE_H

#include <stdint.h>
#include <stdbool.h>

//#include "stm32h5xx_hal.h"

/* 实际需要保存的参数结构体定义 */
//#include "APP_Dev_Config.h"


/* 配置FLASH参数 - 根据实际情况修改 */ 
#define FLASH_SECTOR_SIZE			   (1024*2)
#define CYCLE_FLASH_SECTOR_ADDR        (uint32_t)(0x08100000 + 31*FLASH_SECTOR_SIZE) // 存储Flash扇区起始地址 0X0813E000
#define CYCLE_FLASH_SECTOR_SIZE         8192        // 8K扇区大小
#define PARAMS_DATA_SIZE          		54          // 保存参数预留的数据大小(字节)，根据实际参数调整,务必保证（参数size+10）是16的倍数

/* 参数数据结构 - 根据实际需求定义 */ 
typedef union 
{
    uint8_t reserved[PARAMS_DATA_SIZE];  // 空间占位
	
	// 实际存储的自定义数据类型
	//Storage_Para_t storage_RD;	
	
} DeviceParamsTypeDef;




/*
	初始化标记魔术字，
	用于检测是否首次启动，标志位设置为该扇区的最后四个字节，
	修改魔术字可以在下次更新程序时清空保存的参数
*/ 
#define INIT_MAGIC 		0x12345678
#define INIT_MAGIC_SIZE    (4*sizeof(uint32_t))// 设置 初始化标志位的长度，H5一次写入16字节
#define INIT_MARKER_ADDR (CYCLE_FLASH_SECTOR_ADDR + CYCLE_FLASH_SECTOR_SIZE - INIT_MAGIC_SIZE)


/*
	存储单元大小 = 魔术字(4) + 计数器(4) + 参数数据(PARAMS_DATA_SIZE) + 校验和(2)
*/ 
#define STORAGE_UNIT_SIZE         (4 + 4 + PARAMS_DATA_SIZE + 2) // 需要保证存储单元是 16字节的倍数
#define MAX_STORAGE_UNITS         ((CYCLE_FLASH_SECTOR_SIZE - INIT_MAGIC_SIZE) / STORAGE_UNIT_SIZE)  // 减去初始化标志位大小后，计算最大存储单元数量


#if STORAGE_UNIT_SIZE%16 != 0
#error  "in H5 flash the storage unit must divd by 16"
#endif



/* 状态定义 */ 
#define STORAGE_OK                0
#define STORAGE_ERROR             1
#define STORAGE_NO_VALID_DATA     2

/* 存储魔术字 - 用于验证数据有效性 */ 
#define STORAGE_MAGIC             0x5A5A5A5AUL


// 存储单元结构
typedef struct {
    uint32_t magic;                  // 魔术字，用于验证有效性
    uint32_t counter;                // 计数器，用于判断数据新旧
    DeviceParamsTypeDef params;      // 参数数据
    uint16_t checksum;               // 校验和，用于验证数据完整性
} FlashStorageUnitTypeDef;

// 函数声明
uint8_t FlashStorage_Init(void);
uint8_t FlashStorage_WriteParams(const DeviceParamsTypeDef *params);
uint8_t FlashStorage_ReadLatestParams(DeviceParamsTypeDef *params);
uint8_t FlashStorage_GetParamsCount(void);  // 获取有效参数数量

#endif // FLASH_CYCLE_STORAGE_H
    